home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 05.zip / BS1 part 5 / SASC_6.0_Disk_7.adf / Source_And_Examples / examples / cback / schelp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-30  |  14.9 KB  |  440 lines

  1. /*
  2.     SAS/C Background Example
  3.     SAS/C Help System Hot-Key Example
  4.     version 6.0   1992
  5.  
  6.     This is a program which demonstrates how to write a background process which
  7.     employs a hot-key.  This program will pop up the main interface to the
  8.     SAS/C Help System when control-Help is pressed. 
  9.  
  10.     You should compile this program with the following options:
  11.  
  12.                NOSTACKCHECK
  13.                STRUCTUREEQUIVALENCE
  14.                LINK
  15.                STARTUP=cback
  16.  
  17.     NOSTACKCHECK is suggested because the function handlerStuff can be called
  18.     from a task other than this program.  It would be required if the function
  19.     was not declared with the __interrupt keyword.  This is discussed in more
  20.     detail at the function's definition.
  21.  
  22.     STRUCTUREEQUIVALENCE is not required, but it does circumvent several
  23.     warnings that would otherwise be produced.
  24.  
  25.     STARTUP=cback tells slink to link with the background startup code.  This
  26.     is required to produce a background process.  If you link in a separate step,
  27.     you must link with cback.o instead of c.o.
  28.  
  29.     You should not compile this program with the NOSTANDARDIO option
  30.     because the program's main routine is called "__main".  NOSTANDARDIO
  31.     can only be used on programs whose main routine is called "main".
  32.     This program does not initialize stdin, stdout or stderr, so it
  33.     cannot call printf() or other standard IO functions.  Calling
  34.     these functions will probably crash the machine.
  35.  
  36.     You may notice that this program does not open any AmigaDOS libraries.  Instead
  37.     it takes advantage of the fact that the version 6.0 compiler now opens
  38.     needed libraries for you.
  39.  
  40.     ****  IMPORTANT  ***
  41.     When running CPR on this program or other programs using __main, you
  42.     must perform the following 2 steps to avoid crashing the machine:
  43.     
  44.            1)  As soon as cpr is invoked, select Catch New Tasks from the
  45.                Options menu.  Catch New Tasks must be set to on.
  46.                
  47.            2)  Type 
  48.                     go __main
  49.                     
  50.                This places you at the beginning of your code.  If you say
  51.                go __main without setting Catch New Tasks to on, you will
  52.                probably crash the machine.  
  53.                
  54.      If you try to debug the input handler program HandlerInterface in this
  55.      program, you will probably crash your machine. 
  56.  
  57.      The schelp command takes the following forms:
  58.      
  59.                  schelp
  60.      
  61.      This command will load schelp as a background process, display a copyright
  62.      banner, and display the usage information.  If schelp is already loaded,
  63.      it will simply display the usage information.
  64.      
  65.                  schelp quit
  66.                  
  67.      This command will display a terminating message and unload schelp from
  68.      memory.            
  69.      
  70.                  schelp <command>
  71.                  
  72.      This command will replace the command currently tied to the control-Help
  73.      key with the command designated.  In order for the command to work, it 
  74.      must contain the full path to the command.            
  75.  
  76. */
  77.  
  78. /**************************  INCLUDES  ************************/
  79. #include <exec/types.h>
  80. #include <exec/nodes.h>
  81. #include <exec/lists.h>
  82. #include <exec/memory.h>
  83. #include <exec/interrupts.h>
  84. #include <exec/ports.h>
  85. #include <exec/libraries.h>
  86. #include <exec/io.h>
  87. #include <exec/tasks.h>
  88. #include <exec/execbase.h>
  89. #include <exec/devices.h>
  90. #include <devices/timer.h>
  91. #include <devices/input.h>
  92. #include <devices/inputevent.h>
  93. #include <intuition/intuition.h>
  94. #include <libraries/dos.h>
  95. #include <graphics/gfxmacros.h>
  96. #include <hardware/custom.h>
  97. #include <hardware/dmabits.h>
  98. #include <proto/dos.h>
  99. #include <proto/exec.h>
  100. #include <proto/intuition.h>
  101. #include <proto/graphics.h>
  102. #include <string.h>
  103. #include <stdlib.h>
  104.  
  105.  
  106.  
  107.  
  108. /**************************  CONSTANTS  ***********************/
  109. #define BANNER       "\x9B""0;33mSAS/C Help\x9B""0m Copyright \xA9 1992 SAS Institute, Inc.\n"
  110. #define BANNER1  "Usage: \x9B""1mschelp\x9B""0m [quit] [<command>]\nwhere\n\x9B""1mschelp\x9B""0m           allows you to hit cntrl-Help to pop up the SAS/C Help screen\n\x9B""1mschelp quit\x9B""0m      deletes schelp as a background process\n"
  111. #define BANNER2  "\x9B""1mschelp <command>\x9B""0m allows you to change the command executed when you hit cntrl-Help\n                   *** Include full path to the command\n"
  112. #define DEFCMD       "sc:c/amigaguide sc:help/sc_help.guide\0"
  113. #define DEFKEY       0x5F
  114. #define KILLMSG      "\x9B""1mSAS/C Help\x9B""0m Terminating\n"
  115. #define MAXCMD       200
  116. #define PORTNAME     "SASC_HELP.port"
  117.  
  118.  
  119.  
  120. /*********************** GLOBAL VARIABLES *********************/
  121. typedef struct
  122.    {
  123.    struct Task          *buddy;
  124.    ULONG                 helpsig;
  125.    short                 helpsignum;
  126.    short                 key;
  127.    } GLOBAL_DATA;
  128.  
  129. struct OURMSG {
  130.  struct Message msg_header;
  131.  short  quit;
  132.  char   cmd[MAXCMD];
  133.  };
  134.  
  135.  
  136. typedef void (*vfunc)();
  137.  
  138.  
  139. /**************************  PROTOTYPES  **********************/
  140. void clean_exit(struct IOStdReq *, struct Interrupt, GLOBAL_DATA,
  141.                 struct MsgPort *, BPTR, BPTR, struct MsgPort *,int);
  142.  
  143. struct InputEvent * __asm HandlerInterface(register __a0 struct InputEvent *,
  144.                                     register __a1 GLOBAL_DATA *);
  145.  
  146. struct IOStdReq *CreateIOReq(struct MsgPort *, int);
  147.  
  148. void DeleteIOReq(struct IOStdReq *);
  149.  
  150.  
  151.  
  152. /**********************  CBACK DECLARATIONS  ******************/
  153. long __stack = 4000;              /* Amount of stack space our task needs */
  154. char *__procname = "SAS/C Help";  /* The name of the task to create       */
  155. long __priority = 20;             /* The priority to run the task at    */
  156. long __BackGroundIO = 1;          /* Flag indicating we want to send I/O to the
  157.                                      original shell.  We will print a banner.
  158.                                      NOTE:  This variable may also be called
  159.                                      _BackGroundIO.  Notice the single
  160.                                      underscore.                       */
  161. extern BPTR _Backstdout;          /* File handle pointing to originating shell
  162.                                      (standard output when run in background) */
  163.  
  164. /********************************************************************/
  165.  
  166. void __stdargs __main(char *command)
  167. {
  168.    struct OURMSG *msg, tmpmsg;
  169.    struct MsgPort *port;
  170.    int first_call = 0;
  171.  
  172.    char cmdstr[MAXCMD];
  173.    BPTR  nullfh1, nullfh2;
  174.    ULONG sig;
  175.    struct MsgPort     *inputDevPort;
  176.    struct IOStdReq    *inputRequestBlock;
  177.    struct Interrupt   handlerStuff;
  178.    GLOBAL_DATA global;
  179.  
  180.    global.helpsignum  = -1;
  181.    inputDevPort        = NULL;
  182.    inputRequestBlock   = NULL;
  183.    nullfh1 = nullfh2 = NULL;
  184.  
  185.    /* Check if this program is already loaded, and if not, create a port  */
  186.    if ((port = FindPort(PORTNAME)) == NULL)
  187.       {
  188.       /* Set flag indicating this is the first time the program's been called */
  189.       first_call = 1;
  190.  
  191.       /* Since this is the first call, open the port */
  192.       if ((port = CreatePort(PORTNAME,0)) == NULL)
  193.           clean_exit(inputRequestBlock, handlerStuff, global, inputDevPort,
  194.                 nullfh1, nullfh2, port, first_call);
  195.       }
  196.  
  197.  
  198.    /* Allocate memory for and partially set up the message this program
  199.       will send to itself.                                             */
  200.    if ((msg = (struct OURMSG *)
  201.               AllocMem(sizeof(struct OURMSG), MEMF_CLEAR | MEMF_PUBLIC)) == NULL)
  202.       clean_exit(inputRequestBlock, handlerStuff, global, inputDevPort,
  203.                  nullfh1, nullfh2, port, first_call);
  204.  
  205.    msg->msg_header.mn_Length = sizeof(struct OURMSG);
  206.    msg->quit = 0;
  207.    msg->cmd[0] = 0;
  208.  
  209.    /*  Set up the command to be executed to start SAS/C Help  */
  210.    strcpy(cmdstr, DEFCMD);
  211.  
  212.    /* If this program was run from a CLI, then output the banner
  213.       and process any parameters */
  214.    if (command && *command)
  215.       {
  216.       /* Write the copyright banner if this is the first time the program
  217.          was called.                                                     */
  218.       if (first_call && _Backstdout)
  219.          Write(_Backstdout, BANNER, sizeof(BANNER));
  220.  
  221.       /* Skip to a parameter if one exists */
  222.       while(*command != ' ')
  223.          command++;
  224.       while(*command == ' ')
  225.          command++;
  226.  
  227.  
  228.       /* Evaluate the parameter */
  229.       if (!stricmp(command, "QUIT\n"))
  230.          {
  231.          msg->quit = 1;
  232.          if (_Backstdout)
  233.             Write(_Backstdout, KILLMSG, sizeof(KILLMSG));
  234.          }
  235.  
  236.       /*  If all that is left is a carriage return, print out the usage message */
  237.       else if ((*command < ' ') && _Backstdout)
  238.          {
  239.          Write(_Backstdout, BANNER1, sizeof(BANNER1));
  240.          Write(_Backstdout, BANNER2, sizeof(BANNER2));
  241.          }
  242.       /* Put the rest of the command into the command string to be executed  */
  243.       else
  244.          {
  245.          strcpy(msg->cmd, command);
  246.          msg->cmd[strlen(command)-1] = 0;  /* wipe out the EOL character */
  247.          }
  248.       }
  249.  
  250.    /*  Send the message with instructions on actions to SAS/C Help's port  */
  251.    PutMsg (port,(struct Message *) msg);
  252.  
  253.    /*  If this is the first time this program is called, set up the input
  254.        handler, etc.   */
  255.    if (!first_call)
  256.       clean_exit(inputRequestBlock, handlerStuff, global, inputDevPort,
  257.                 nullfh1, nullfh2, port, first_call);
  258.  
  259.    /* Close _Backstdout so that the original window can go away */
  260.    if (_Backstdout)
  261.       Close(_Backstdout);
  262.  
  263.    _Backstdout = 0;
  264.  
  265.  
  266.    /* set the input and output streams to 0 so execute doen't complain */
  267.    nullfh1 = Open("NIL:", MODE_NEWFILE);
  268.    nullfh2 = Open("NIL:", MODE_NEWFILE);
  269.  
  270.    if (((inputDevPort = CreatePort(0,0)) == NULL)  ||
  271.  
  272.       ((inputRequestBlock =
  273.           CreateIOReq(inputDevPort, sizeof(struct IOStdReq))) == NULL)  ||
  274.  
  275.       ((global.helpsignum = AllocSignal(-1)) == -1)  ||
  276.  
  277.       OpenDevice("input.device",0,(struct IORequest *)inputRequestBlock,0))
  278.  
  279.       clean_exit(inputRequestBlock, handlerStuff, global, inputDevPort,
  280.                 nullfh1, nullfh2, port, first_call);
  281.  
  282.    /*  Set up stuff for input handler  */
  283.    handlerStuff.is_Data = (APTR) &global;
  284.    handlerStuff.is_Code = (vfunc) HandlerInterface;
  285.    handlerStuff.is_Node.ln_Pri = 51;
  286.  
  287.    /*  Set up global data to be used by input handler  */
  288.    global.buddy = FindTask(0);
  289.    global.helpsig  = 1 << global.helpsignum;
  290.    global.key = DEFKEY;
  291.  
  292.    inputRequestBlock->io_Command = IND_ADDHANDLER;
  293.    inputRequestBlock->io_Data    = (APTR)&handlerStuff;
  294.  
  295.    DoIO((struct IORequest *)inputRequestBlock);
  296.  
  297.    for(;;)         /* FOREVER */
  298.       {
  299.       sig = Wait( global.helpsig | (1 << port->mp_SigBit) );
  300.  
  301.       /* Check contents of message and quit or change the command to be
  302.          executed                                                     */
  303.       if (sig & (1 << port->mp_SigBit))
  304.          {
  305.          while ((msg = (struct OURMSG *)GetMsg(port)) != NULL)
  306.             {
  307.             tmpmsg = *msg;
  308.             ReplyMsg ( (struct Message *) msg);
  309.             if (tmpmsg.quit)
  310.                clean_exit(inputRequestBlock, handlerStuff, global,
  311.                           inputDevPort, nullfh1, nullfh2, port, first_call);
  312.             if (tmpmsg.cmd[0])
  313.                strcpy(cmdstr, msg->cmd);
  314.             }
  315.          }
  316.  
  317.       /*  Execute the command  */
  318.       if (sig & global.helpsig)
  319.          {
  320.          (void)Execute(cmdstr,nullfh1,nullfh2);
  321.          }
  322.       }
  323. }
  324.  
  325. /********************************************************************/
  326.  
  327. /*  Clean up and exit */
  328. void clean_exit(struct IOStdReq *inputRequestBlock, struct Interrupt
  329.      handlerStuff, GLOBAL_DATA global, struct MsgPort *inputDevPort,
  330.      BPTR nullfh1, BPTR nullfh2, struct MsgPort * port, int first_call)
  331. {
  332.    if(_Backstdout)
  333.       Close(_Backstdout);
  334.  
  335.    if (inputRequestBlock != NULL)
  336.       {
  337.       if (inputRequestBlock->io_Device != NULL)
  338.          {
  339.          inputRequestBlock->io_Command = IND_REMHANDLER;
  340.          inputRequestBlock->io_Data = (APTR)&handlerStuff;
  341.          DoIO((struct IORequest *)inputRequestBlock);
  342.  
  343.          CloseDevice((struct IORequest *)inputRequestBlock);
  344.          }
  345.       DeleteIOReq(inputRequestBlock);
  346.       }
  347.    if (global.helpsignum != -1)   
  348.        FreeSignal(global.helpsignum);
  349.    if (inputDevPort != NULL)       
  350.        DeletePort(inputDevPort);
  351.    if (first_call && (port != NULL)) 
  352.        DeletePort(port);
  353.    if (nullfh1)  
  354.        Close(nullfh1);
  355.    if (nullfh2)  
  356.        Close(nullfh2);
  357.  
  358.    exit(0);
  359. }
  360.  
  361.  
  362.  
  363. /************************************************************************/
  364.  
  365. /* This routine is the input handler function.  It is put into the input
  366.    handler list at a priority above Intuition's so that it can check
  367.    all input for the SAS/C Help key sequence.                           */
  368.  
  369. /* Note the use of the __interrupt keyword below.  This is used to   */
  370. /* prohibit the generation of stack-checking or stack-extension code */
  371. /* if the module is compiled with the STACKCHECK or STACKEXT options.*/
  372. /* (STACKCHECK is the default).  Because this function is called     */
  373. /* directly from input.device, it will be using input.device's stack */
  374. /* and not the program's stack; hence code that relies on using the  */
  375. /* program's stack must be disabled.                                 */
  376.  
  377. struct InputEvent * __interrupt __asm HandlerInterface(
  378.                      register __a0 struct InputEvent *event,
  379.                      register __a1 GLOBAL_DATA *gptr)
  380. {
  381.    register struct InputEvent *cur_event, *last_event;
  382.  
  383.    /* Step through the event list, checking for SAS/C Help key sequence  */
  384.    for (cur_event = event, last_event = NULL; cur_event != NULL;
  385.                    cur_event = cur_event->ie_NextEvent)
  386.       {
  387.       if ((cur_event->ie_Class == IECLASS_RAWKEY)    &&
  388.           (cur_event->ie_Code  == gptr->key)         &&
  389.           (cur_event->ie_Qualifier & IEQUALIFIER_CONTROL))
  390.          {
  391.          /*  This event was our key sequence, so take it off of the event chain */
  392.          if (last_event == NULL)
  393.             event = cur_event->ie_NextEvent;
  394.          else
  395.             event = last_event->ie_NextEvent = cur_event->ie_NextEvent;
  396.  
  397.          /* Notify the SAS/C Help task to pop up the help window */
  398.          Signal(gptr->buddy, gptr->helpsig);
  399.          }
  400.       else
  401.          last_event = cur_event;
  402.  
  403.       }
  404.    /* Return the pointer to the event */
  405.    return(event);
  406. }
  407.  
  408.  
  409. /************************************************************************/
  410.  
  411.  
  412. struct IOStdReq *CreateIOReq(struct MsgPort *port, int size)
  413. {
  414.    struct IOStdReq *ioReq;
  415.  
  416.    if ((ioReq = (struct IOStdReq *)
  417.                 AllocMem(size, MEMF_CLEAR | MEMF_PUBLIC)) != NULL)
  418.       {
  419.       ioReq->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  420.       ioReq->io_Message.mn_Node.ln_Pri  = 0;
  421.       ioReq->io_Message.mn_Length       = size;
  422.       ioReq->io_Message.mn_ReplyPort    = port;
  423.       }
  424.    return(ioReq);
  425. }
  426.  
  427.  
  428. /************************************************************************/
  429.  
  430.  
  431.  
  432. void DeleteIOReq (struct IOStdReq *ioReq)
  433. {
  434.    ioReq->io_Message.mn_Node.ln_Type = 0xff;
  435.    ioReq->io_Device = (struct Device *) -1;
  436.    ioReq->io_Unit = (struct Unit *) -1;
  437.  
  438.    FreeMem( (char *)ioReq, ioReq->io_Message.mn_Length);
  439. }
  440.